﻿using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;

public class ClientBase {

    protected bool isServer = true;
    public bool IsServer { get { return isServer; } }
    /// <summary>
    /// 接收最大长度
    /// </summary>
    protected const int MAX_BUFF_LENGTH = 1024;

    /// <summary>
    /// 读取数据数组
    /// </summary>
    protected byte[] readBuff = new byte[MAX_BUFF_LENGTH];

    /// <summary>
    /// 消息缓冲列表
    /// </summary>
    protected List<byte> dataCache = new List<byte>();

    /// <summary>
    /// 客户端socket
    /// </summary>
    protected Socket clientSocket;

    /// <summary>
    /// 是否按长度解析
    /// </summary>
    protected bool isPacketDecode = true;

    /// <summary>
    /// 互斥锁
    /// </summary>
    protected static readonly Mutex mux = new Mutex();

    /// <summary>
    /// 解析数据
    /// </summary>
    /// <param name="dataCache"></param>
    /// <returns></returns>
    private byte[] DecodePacket(ref List<byte> dataCache)
    {
        if (isPacketDecode)
        {
            if (dataCache.Count < sizeof(int))
            {
                return null;
            }
            byte[] dataCacheArray = dataCache.ToArray();
            int len = BitConverter.ToInt32(dataCacheArray, 0);
            if (len > dataCache.Count - sizeof(int))
            {
                //Console.WriteLine("无法构成数据包，长度不足");
                return null;
            }
            dataCache.RemoveRange(0, len + sizeof(int));
            byte[] msgData = new byte[len];
            Buffer.BlockCopy(dataCacheArray, sizeof(int), msgData, 0, len);
            return msgData;
        }
        else
        {
            if (dataCache.Count <= 0)
            {
                return null;
            }
            else
            {
                byte[] dataCacheArray = dataCache.ToArray();
                dataCache.RemoveRange(0, dataCache.Count);

                return dataCacheArray;
            }
        }
    }

    /// <summary>
    /// 接收消息
    /// </summary>
    /// <param name="ar"></param>
    protected void ReceiveCb(IAsyncResult ar)
    {
        mux.WaitOne();
        if (clientSocket == null || !clientSocket.Connected)
        {

            mux.ReleaseMutex();
            return;
        }
        bool isRunException = false;
        try
        {
            int len = clientSocket.EndReceive(ar);
            mux.ReleaseMutex();
            byte[] data = new byte[len];
            Buffer.BlockCopy(readBuff, 0, data, 0, len);
            dataCache.AddRange(data);

            if (len <= 0)
            {
                //服务器关闭
                //UnityEngine.Debug.Log("断开连接");
                Close(NetEventType.COMM_DISCONNECT_INITIATIVE, "断开连接");
                return;
            }
            //处理消息
            HandleReceive();

        }
        catch (Exception ex)
        {
            mux.ReleaseMutex();
            isRunException = true;
            //UnityEngine.Debug.Log("异常，断开");
            //客户端死机
            //网络异常
            //强制断开连接的时候
            //调试程序关闭
            Close(NetEventType.COMM_DISCONNECT_EXCEPTION, ex.Message);
            return;
        }
        if (isRunException) return;

        mux.WaitOne();
        try
        {
            clientSocket.BeginReceive(readBuff, 0, MAX_BUFF_LENGTH, SocketFlags.None, ReceiveCb, null);
            mux.ReleaseMutex();
        }
        catch (Exception ex)
        {
            mux.ReleaseMutex();
            CoreEvent ce = new CoreEvent();
            ce.eventType = NetEventType.COMM_START_ASYNC_RECEIVE_THREAD_FAILED;
            ce.log = ex.Message;
            NetCore.AddEvent(ce);
        }


    }

    /// <summary>
    /// 处理消息
    /// </summary>
    private void HandleReceive()
    {
        byte[] data = DecodePacket(ref dataCache);
        if (data == null)
        {
            return;
        }

        CoreEvent ce = new CoreEvent();
        ce.eventType = NetEventType.COMM_RECEIVE_MESSAGE;
        ce.data = data;
        ce.sender = this;
        NetCore.AddEvent(ce);
        HandleReceive();
    }

    /// <summary>
    /// 关闭
    /// </summary>
    protected virtual void Close(NetEventType type, string log) { }

    public virtual int Send(byte[] msg) { return 0; }

    public virtual void Close() { }
}
